/******************************************************
 * @file utf-8.c
 * @author Destiny 
 * @brief utf-8解码程序
 * 
 * @version 0.1
 * @date 2024-07-18
 *****************************************************/
#include <config.h>
#include <encoding_manager.h>
#include <string.h>

static int isUtf8Coding(uint8_t *pucBufHead);        /*是否是UTF-8编码方式*/
static int Utf8GetCodeFrmBuf(uint8_t *pucBufStart, uint8_t *pucBufEnd, uint32_t *pdwCode);  /*解码*/
/*构造UTF-8解码操作结构体*/
static T_EncodingOpr g_tUtf8EncodingOpr = {
	.name          = "utf-8",
	.iHeadLen	   = 3,
	.isSupport     = isUtf8Coding,
	.GetCodeFrmBuf = Utf8GetCodeFrmBuf,
};
/*
 * @description		    	: 判断该文件是否是UTF-8编码方式
 * @param - pucBufHead	 	: 文件起始地址
 * @return 			    	: 1 是;其他 不是
 */
static int isUtf8Coding(uint8_t *pucBufHead)
{
	const char aStrUtf8[]    = {0xEF, 0xBB, 0xBF, 0};  /*UTF-8编码文件头*/
	if (strncmp((const char*)pucBufHead, aStrUtf8, 3) == 0)
	{
		
		return 1;
	}
	else
	{
		return 0;
	}
}
/*
 * @description		    	: 得到UTF-8编码长度
 * @param - ucVal		 	: 字符的第一个字节
 * @return 			    	: UTF-8编码字节数
 */
static int GetPreOneBits(uint8_t ucVal)
{
	int i;
	int j = 0;
	
	for (i = 7; i >= 0; i--)
	{
		if (!(ucVal & (1<<i)))
			break;
		else
			j++;
	}
	return j;

}
/*
    对于UTF-8编码中的任意字节B，如果B的第一位为0，则B为ASCII码，并且B独立的表示一个字符;
    如果B的第一位为1，第二位为0，则B为一个非ASCII字符（该字符由多个字节表示）中的一个字节，并且不为字符的第一个字节编码;
    如果B的前两位为1，第三位为0，则B为一个非ASCII字符（该字符由多个字节表示）中的第一个字节，并且该字符由两个字节表示;
    如果B的前三位为1，第四位为0，则B为一个非ASCII字符（该字符由多个字节表示）中的第一个字节，并且该字符由三个字节表示;
    如果B的前四位为1，第五位为0，则B为一个非ASCII字符（该字符由多个字节表示）中的第一个字节，并且该字符由四个字节表示;

    因此，对UTF-8编码中的任意字节，根据第一位，可判断是否为ASCII字符;
    根据前二位，可判断该字节是否为一个字符编码的第一个字节; 
    根据前四位（如果前两位均为1），可确定该字节为字符编码的第一个字节，并且可判断对应的字符由几个字节表示;
    根据前五位（如果前四位为1），可判断编码是否有错误或数据传输过程中是否有错误。
*/
/*
 * @description		    	: UTF-8解码函数
 * @param - pucBufStart 	: 文件当前读取起始地址
 * @param - pucBufEnd 		: 文件尾部地址
 * @param - pdwCode 		: unicode编码
 * @return 			    	: 编码字节数
 */
static int Utf8GetCodeFrmBuf(uint8_t *pucBufStart, uint8_t *pucBufEnd, uint32_t *pdwCode)
{
	int i;	
	int iNum;
	uint8_t ucVal;
	uint32_t dwSum = 0;
	/* 地址错误 */
	if (pucBufStart >= pucBufEnd)
	{
		return 0;
	}
	/* 得到UTF-8编码长度 */
	ucVal = pucBufStart[0];
	iNum  = GetPreOneBits(pucBufStart[0]);
	/*超出范围*/
	if ((pucBufStart + iNum) > pucBufEnd)
	{
		return 0;
	}
	/*为ASCII字符*/
	if (iNum == 0)
	{	
		*pdwCode = pucBufStart[0];
		return 1;
	}
	else
	{
		/*UTF-8转换为unicode*/
		ucVal = ucVal << iNum;
		ucVal = ucVal >> iNum;
		dwSum += ucVal;
		for (i = 1; i < iNum; i++)
		{
			ucVal = pucBufStart[i] & 0x3f;
			dwSum = dwSum << 6;
			dwSum += ucVal;			
		}
		*pdwCode = dwSum;
		return iNum;
	}
}
/*
 * @description		    	: 解码方法初始化
 * @param - 			 	: 无
 * @return 			    	: 0 成功;其他 失败
 */
int  Utf8EncodingInit(void)
{
	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("freetype"));
	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("ascii"));
	return RegisterEncodingOpr(&g_tUtf8EncodingOpr);
}

